<template>
  <div
    class="video-container"
    element-loading-background="rgba(0, 0, 0, 0.7)"
    element-loading-spinner="el-icon-loading"
    element-loading-text="正在缓冲..."
    v-loading="loading"
  >
    <div class="header">
      <div class="animation">
        <div
          :style="{ width: `${bufferValue}%` }"
          class="process"
        />
        <div
          :style="{ width: `${playedValue}%` }"
          class="played"
        />
      </div>
      <div class="text">
        <div class="process">
          <span v-if="videoInfo.channelNum">已缓冲：{{ bufferValue + '%' }}</span>
          <!-- <span v-if="videoInfo.channelNum">{{ `${this.bufferedTime}-${this.duration}` }}</span> -->
        </div>
        <div class="title">
          {{ videoInfo.channelNum || '无视频信号' }}{{ videoInfo.channelName }}
        </div>
      </div>
    </div>
    <div class="content">
      <video
        ref="video"
        v-if="videoInfo.fileSrc"
        v-show="!showSnapshoot"
        :id="id"
        :muted="muted"
        :src="videoInfo.fileSrc"
        :defaultMuted="defaultMuted"
        :preload="preloadValue"
        :volume="volumeValue"
        :playbackRate="playbackRate"
        crossOrigin="anonymous"
        @abort="abort"
        @canplay="canplay"
        @canplaythrough="canplaythrough"
        @durationchange="durationchange"
        @emptied="emptied"
        @ended="ended"
        @error="error"
        @loadeddata="loadeddata"
        @loadedmetadata="loadedmetadata"
        @loadstart="loadstart"
        @pause="pause"
        @play="playHandle"
        @playing="playing"
        @progress="progress"
        @ratechange="ratechange"
        @seeked="seeked"
        @seeking="seeking"
        @stalled="stalled"
        @suspend="suspend"
        @timeupdate="timeupdate"
        @volumechange="volumechange"
        @waiting="waiting"
        @fullscreenchange="fullscreenchange"
      />
      <div
        v-if="showSnapshoot"
        class="img-content"
      >
        <img :src="snapshootUrl">
      </div>
    </div>
    <!-- <div v-if="!status" class="error">
      <el-button size="mini" type="primary" @click="reload" round>重新加载</el-button>
    </div> -->
  </div>
</template>

<script>
// import { Component, Vue, Watch, Prop, Emit } from 'vue-property-decorator'
// import { PostbirdMp4ToBlob } from '@/utils/convert'
// import { uuid } from '@/utils'
export default {
  data(){
    return{
      loading: false,
      snapshootUrl: '',
      width: 0,
      height: 0,
      status: 1,// 0出错，1正常
      timer: null,// 加载状态定时器
      duration: 1,// 视频总秒数
      bufferedTime: 0,//已缓存视频秒数
      currentTime: 0, // 已播放的时间
      isFullScreen: false, //是否全屏状态
      playbackRate: ''
    }
  },
  Prop: {
    id: {
      type: String,
      default() {
        return uuid(15)
      }
    },
    videoInfo: {
      type: Object,
      default() {
        return {}
      }
    },
    play: {
      type: Boolean,
      default: false
    },
    nowTime: {
      type: Number,
      default: 0
    },
    volumeValue: {
      type: Number,
      default: 100
    },
    defaultMuted: {
      type: Boolean,
      default: false
    },
    playbackRate: {
      type: Number,
      default: 1.0
    },
    showScreenshot: {
      type: Boolean,
      default: false
    },
    muted: {
      type: Boolean,
      default: false
    },
    preload: {
      type: Boolean,
      default: true
    }
  },
  mounted() {
    // /播放速率
    this.playbackRate = this.playbackRateOptions[this.playbackRateIndex]
  },
  methods: {
    showSnapshoot() {
    // 判断图片是否有效
      if (!this.snapshootUrl || this.snapshootUrl.length < 50) return false
      return this.showScreenshot
    },
    defaultPlaybackRate() {
      return 1.0
    },
    bufferValue() {
      const value = this.bufferedTime / this.duration * 100
      return parseFloat(value.toFixed(2) || '0')
    },
    playedValue() {
      const value = this.currentTime / this.duration * 100
      return value.toFixed(2)
    },
    preloadValue() {
      return this.preload ? 'auto' : 'metadata'
    },
    playValue() {
      // 判断是否是加载中状态
      if (this.loading) {
        return true
      }
      return this.play
    },
    abort(e) {
      console.error(this.videoInfo.channelName + '：视频的加载已放弃')
      this.setLoading(false)
      this.getBuffered(e.target)
    },
    canplay(e) {
      // console.log(this.videoInfo.channelName + '：浏览器可以播放视频')
      this.getSnapshoot()
      this.$emit('canplay-vedio', e.target.duration)
    },
    canplaythrough() {
      // console.log(this.videoInfo.channelName + '：浏览器可在不因缓冲而停顿的情况下进行播放')
    },
    durationchange() {
    // console.log(this.videoInfo.channelName + '：视频的时长已更改')
    },
    emptied() {
    // console.error(this.videoInfo.channelName + '：目前的播放列表为空')
  },
  ended(e) {
    // console.log(this.videoInfo.channelName + '：目前的播放列表已结束')
    this.setLoading(false)
    this.$emit('ended', e)
  },
  error(e) {
    // console.error(this.videoInfo.channelName + '：视频加载期间发生错误')
    this.setLoading(false)
    this.status = 0
  },
  loadeddata(e) {
    // console.log(this.videoInfo.channelName + '：浏览器已加载视频的当前帧')
    this.setLoading(false)
    this.getBuffered(e.target)
  },
  loadedmetadata(e) {
    // console.log(this.videoInfo.channelName + '：浏览器已加载视频的元数据')
    this.setLoading(false)
    if (!e.target) return
    // 获取视频的宽跟高
    const video = e.target
    this.width = video.videoWidth
    this.height = video.videoHeight
    this.getBuffered(e.target)
  },
  loadstart(e) {
    // console.log(this.videoInfo.channelName + '浏览器开始查找视频')
    this.getBuffered(e.target)
    if (this.bufferValue < 100 && this.currentTime >= this.bufferedTime) {
      this.setLoading(true)
    }
  },
  pause() {
    // console.log(this.videoInfo.channelName + '：视频已暂停')
    if (this.isFullScreen && !this.loading) {
      this.$emit('pause')
    }
  },
  playHandle(e) {
    // console.log(this.videoInfo.channelName + '：视频已开始或不再暂停')
    this.getBuffered(e.target)
    if (this.isFullScreen && !this.loading) {
      this.$emit('play')
    }
  },
  playing(e) {
    // console.log(this.videoInfo.channelName + '：视频在已因缓冲而暂停或停止后已就绪')
    this.setLoading(false)
    this.getBuffered(e.target)
  },
  progress(e) {
    // console.log(this.videoInfo.channelName + '：浏览器正在下载视频')
    this.getBuffered(e.target)
  },
  ratechange() {
    // console.log(this.videoInfo.channelName + '：视频的播放速度已更改')
  },
  seeked(e) {
    // console.log(this.videoInfo.channelName + '：用户已移动/跳跃到视频中的新位置')
    // this.setLoading(false)
    this.getSnapshoot()
    this.getBuffered(e.target)
  },
  stalled(e) {
    console.error(this.videoInfo.channelName + '：浏览器尝试获取媒体数据，但数据不可用')
    this.getBuffered(e.target)
    if (this.bufferValue < 100 && this.currentTime >= this.bufferedTime) {
      this.setLoading(true)
    }
  },
  suspend(e) {
    // console.error(this.videoInfo.channelName + '：浏览器刻意不获取媒体数据')
    this.getBuffered(e.target)
  },
  timeupdate(e) {
    // 当目前的播放位置已更改时
    const currentTime = e.target.currentTime
    this.$emit('timeupdate', currentTime)
    this.currentTime = currentTime
    this.getBuffered(e.target)
  },
  volumechange() {
    // console.log(this.videoInfo.channelName + '：音量已更改')
  },
  waiting(e) {
    console.error(this.videoInfo.channelName + '：视频由于需要缓冲下一帧而停止')
    this.getBuffered(e.target)
    this.setLoading(true)
  },
  setLoading(value) {
    if (!this.videoInfo.fileSrc) return
    this.loading = value
    if (value) {
      window.clearTimeout(this.timer)
      this.timer = setTimeout(() => {
        // 加载超时后将loading值置为false
        this.loading = false
      }, 30000)
    } else {
      window.clearTimeout(this.timer)
    }
  },
  // 截取视频快照
  getSnapshoot() {
    if (!this.$refs.video) return Promise.resolve()
    const video = this.$refs.video
    // 创建画布
    const canvas = document.createElement('canvas')
    // 获取画布上下文
    const context = canvas.getContext('2d')
    // 设置画布的宽和高
    canvas.width = this.width
    canvas.height = this.height
    context.fillRect(0, 0, this.width, this.height)
    this.$nextTick(async() => {
      context.drawImage(video, 0, 0, this.width, this.height)
      const dataUrl = canvas.toDataURL('image/jpeg')
      this.snapshootUrl = dataUrl
      return Promise.resolve(dataUrl)
    })
  },
  getBuffered(video = {}) {
    this.duration = video.duration || this.duration
    if (video.buffered && video.buffered.length !== 0) {
      try {
        this.bufferedTime = video.buffered.end(video.buffered.length - 1)
      } catch (e) {}
    }
  },
  setPlaybackRate(value, video) {
    // 判断是否是小数，若不是则保存一位小数
    const rate = this.defaultPlaybackRate * value
    const val = rate === ~~rate ? parseFloat(rate.toFixed(1)) : rate
    video.playbackRate = val
  },
fullScreen() {
    const video = this.$refs.video
    if (video.requestFullscreen) {
      video.requestFullscreen()
    } else if (video.mozRequestFullScreen) {
      video.mozRequestFullScreen()
    } else if (video.webkitRequestFullScreen) {
      video.webkitRequestFullScreen()
    }
  },
  // 退出全屏
  exitFullscreen() {
    const video = this.$refs.video
    if (video.exitFullscreen) {
      video.exitFullscreen()
    } else if (video.mozCancelFullScreen) {
      video.mozCancelFullScreen()
    } else if (video.webkitCancelFullScreen) {
      video.webkitCancelFullScreen()
    }
  },
  fullscreenchange(e) {
    const video = e.target
    this.isFullScreen = video.webkitDisplayingFullscreen
  }
  },
  Watch: {
    'playValue'(){
      if (!this.$refs.video) return
      this.status = 1
      const video = this.$refs.video
      this.getBuffered(video)
      if (this.playValue) {
        video.play()
      } else {
        video.pause()
      }
    },
    'nowTime'(){
      if (!this.$refs.video) return
       (this.$refs.video).currentTime = this.nowTime
    },
    'videoInfo'(){
      const video = this.$refs.video
      this.onPlaybackRateChange()
      this.onVolumeValueChange()
      this.getBuffered(video)
      this.onPlayChange()
    },
    'volumeValue'(){
        if (!this.$refs.video) return
        const volume = Number(this.volumeValue / 100)
        const video = this.$refs.video
        if (volume === 0) {
          video.muted = true
        } else {
          video.muted = this.muted
        }
        this.$nextTick(() => {
          video.volume = volume
        })
    },
    'playbackRate'(){
        if (!this.$refs.video) return
        this.setPlaybackRate(this.playbackRate, this.$refs.video)
    },
    'loading'(){
        if (this.loading) {
          this.getSnapshoot()
        }
        return this.loading
    }
  }
}
</script>
<style scoped>
.video-container {
  height: 100%;
  width: 100%;
  display: flex;
  justify-content: start;
  align-items: center;
  flex-direction: column;
  position: relative;
}
 .video-container .error {
    width: 100%;
    height: 100%;
    position: absolute;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: #909399b0;
  }
.video-container  .content {
    box-sizing: border-box;
    width: 100%;
    height: calc(100% - 15px);
    background-color: #008080;

  }
  .video-container  .content  video {
    display: block;
    width: 100%;
    height: 100%;
    background: #008080;
    outline: none;
    object-fit: fill;
  }
  video::-webkit-media-controls-enclosure {
    /*禁用播放器控制栏的样式*/
    display: none!important;
  }
  .video-container  .content  .img-content {
    display: flex;
    justify-content: center;
    align-items: center;
    flex: 1;
    height: 100%;
  }
  .video-container  .content  .img-content img {
    width: 100%;
    height: 100%;
  }

 .video-container .header {
    position: relative;
    height: 15px;
    width: 100%;
    background: #2f6d92;
    font-size: 12px;
    color: white;
  }
    .video-container .header  .animation {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    height: 100%;
    width: 100%;
  }
  .video-container .header  .animation .process {
    z-index: 1;
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    background-color: #4CAF50;
  }
  .video-container .header  .animation .played {
    z-index: 2;
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    background-color: #009688;
  }
  .video-container .header  .text {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 99;
    height: 100%;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;

  }
  .video-container .header  .text    .process {
    color: white;
  }
  .video-container .header  .text .title {
    color: white;
  }
</style>
